import * as THREE from "three";
import { isArray, isBoolean, isFunction, isNull, isNumber, isString } from "./browser";
import { fract } from "./math";

/**
 * 3维转换
 * @param value 
 * @returns 
 */
export function parseVector3([x, y, z] = [0, 0, 0]) {
    return new THREE.Vector3(parseFloat(x), parseFloat(y), parseFloat(z));
}

export function addVector(v1, v2) {
    if (isArray(v2)) {
        return [v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]];
    } else if (isNumber(v2)) {
        return [v1[0] + v2, v1[1] + v2, v1[2] + v2];
    }
};

/**
 * 进度中获取索引
 * @param array 
 * @param progress 
 * @param steps 
 * @returns 
 */
export function getArrayIndexFromProgress(array, progress, steps) {
    if (!array.length) {
        return -1;
    }

    if (progress >= 1) {
        return array.length - 1;
    }

    if (steps) {
        let curProgress = 0;
        for (let i = 0; i < steps.length; i++) {
            const step = steps[i];
            const endProgress = curProgress + step;
            if (endProgress >= progress) {
                return i;
            }

            curProgress += step;
        }
    } else {
        const step = 1 / array.length;
        const index = Math.floor(progress / step);
        return Math.min(index, array.length - 1);
    }
}

/**
 * 获取数组路径
 * @param array 
 * @param progress 
 * @param steps 
 * @returns 
 */
export function getArrayProgress(array, progress, steps) {
    if (!array.length) {
        return 0;
    }

    if (progress >= 1) {
        return 1;
    }

    if (steps) {
        let curProgress = 0;
        for (let i = 0; i < steps.length; i++) {
            const step = steps[i];
            const endProgress = curProgress + step;
            const deltaProgress = endProgress - progress;
            if (deltaProgress >= 0) {
                return 1 - deltaProgress / step;
            }

            curProgress += step;
        }
    } else {
        const step = 1 / array.length;
        return fract(progress / step);
    }
}

/**
 * 速度计算时间
 * @param array 
 * @param from 
 * @param to 
 * @param time 
 * @param speed 
 * @param defaultTime 
 * @returns 
 */
export function getConsumeTime(array, from, to, time, speed, defaultTime) {
    if (speed) {
        var fromPos = parseVector3([from.x, from.y, from.z]);
        var toPos = parseVector3([to.x, to.y, to.z]);

        var distance = fromPos.distanceTo(toPos);
        return distance / speed * 1000;
    }
    // 直接使用时间
    else if (time !== undefined) {
        if (array) {
            return time / array.length;
        } else {
            return time;
        }
    }
    // 时间和速度都没有提供，那么就返回默认时间
    else {
        return defaultTime;
    }
}

export function buildMoveRaw(obj,path){
    const param = {}
    const {position,rotation,scale} = path || {};
    if(position){
        param['position'] =  [obj.position, position]
    }

    if(rotation){
        param['rotation'] =  [obj.rotation, rotation]
    }

    if(scale){
        param['scale'] =  [obj.scale, scale]
    }  
    return param
}

/**
 * 获取对象自身的属性值
 * @param object 
 * @param key 
 * @returns 
 */
export function getAttribute(object, key) {
    if (!object || !key) {
        return undefined;
    }

    var keys = key.split("/");
    for (var i = 0; i < keys.length; i++) {
        object = object[keys[i]];
        if (!object) {
            return undefined;
        }
    }

    return object;
}

/**
 * 函数结构 code 
 * @param selector  选择器
 * @param userData  用户数据
 * @param callback  回调
 * @param tag 类型
 * @param priority 优先级
 * @returns 
 */
export function parseEvent(selector, userData = undefined || null, callback= undefined || null, tag= undefined || null,
     priority= undefined || null) {
    if (selector) {
        // 直接使用 callback function + tag Name
        if (isFunction(selector) && isString(userData) && isBoolean(callback)) {
            return { selector: null, userData: null, callback: selector, tag: userData };
        }

        // 直接使用 callback function + tag Name
        if (isFunction(selector) && isString(userData) && isNull(callback) && isNull(tag)) {
            return { selector: null, userData: null, callback: selector, tag: userData };
        }

        // 直接使用 callback function + tag Name + priority
        if (isFunction(selector) && isString(userData) && isNumber(callback) && isNull(tag)) {
            return { selector: null, userData: null, callback: selector, tag: userData, priority: callback };
        }

        // 直接使用 callback function + (userData as priority)
        if (isFunction(selector) && isNumber(userData) && isNull(callback) && isNull(tag)) {
            return { selector: null, userData: null, callback: selector, tag: null, priority: userData };
        }

        // 直接使用 callback function + priority
        if (isFunction(selector) && isNull(userData) && isNull(callback) && isNull(tag) && isNumber(priority)) {
            return { selector: null, userData: null, callback: selector, tag: null, priority: priority };
        }

        // 直接使用 callback function
        if (isFunction(selector) && isNull(userData) && isNull(callback) && isNull(tag)) {
            return { selector: null, userData: null, callback: selector };
        }

        // 直接使用 callback function
        if (isFunction(selector) && isBoolean(userData) && isNull(callback) && isNull(tag)) {
            return { selector: null, userData: null, callback: selector };
        }

        // 使用 selector + callback function
        if (isString(selector) && isFunction(userData) && isNull(callback) && isNull(tag)) {
            return { selector: selector, userData: null, callback: userData };
        }

        // 使用 selector + other name
        if (isString(selector) && isNull(userData) && isString(callback) && isNull(tag)) {
            return { selector: selector, userData: null, callback: null, tag: callback };
        }

        // 使用 selector + callback function + tag Name
        if (isString(selector) && isFunction(userData) && isString(callback) && isNull(tag)) {
            return { selector: selector, userData: null, callback: userData, tag: callback };
        }

        // 使用 selector + callback function + tag Name + priority
        if (isString(selector) && isFunction(userData) && isString(callback) && isNumber(tag) && isNull(priority)) {
            return { selector: selector, userData: null, callback: userData, tag: callback, priority: tag };
        }

        // 使用 selector + callback function + priority
        if (isString(selector) && isFunction(userData) && isNumber(callback) && isNull(tag)) {
            return { selector: selector, userData: null, callback: userData, priority: callback };
        }

        // 使用 userData + callback function
        if (isFunction(userData) && isNull(callback)) {
            return { selector: null, userData: selector, callback: userData };
        }

        // 使用 userData + callback function + tag
        if (isFunction(userData) && isString(callback) && isNull(tag)) {
            return { selector: null, userData: selector, callback: userData, tag: callback };
        }

        // 使用 selector
        if (isNull(userData) && isNull(callback) && isNull(tag) && isNull(priority)) {
            return { selector: selector, userData: null, callback: null, tag: null };
        }
    } else {
        // 直接使用 callback function + tag name
        if (isFunction(userData) && isString(callback)) {
            return { selector: null, userData: null, callback: userData, tag: callback };
        }

        // 直接使用 callback function
        if (isFunction(userData) && !isFunction(callback)) {
            return { selector: null, userData: null, callback: userData };
        }

        // 直接使用 tag name
        if (isNull(userData) && isString(callback)) {
            return { selector: null, userData: null, callback: null, tag: callback };
        }
    }

    // 参数合法性检测
    if (selector && !isString(selector)) {
        console.error('Event: selector is invalid');
    }
    if (callback && !isFunction(callback)) {
        console.error('Event: callback is invalid');
    }
    if (tag && !isString(tag)) {
        console.error('Event: tag is invalid');
    }

    // 设置默认值
    if (isNull(priority)) {
        priority = 50;
    }

    return { selector: selector, userData: userData, callback: callback, tag: tag, priority: priority };
}

export function checkSceneJson(data) {
    const { id, sceneUrl } = data;

    const storeName = 'threex_Poc_Scene';
    let localData = THREEX.App.indexStorage.getLocalStorage(storeName);

    if(localData.id === id && localData.sceneUrl === sceneUrl) {

        return true;
    } else {
        return false;
    }
}

export function lon2xyz(R, longitude,latitude) {
    const lon = longitude * Math.PI / 180;
    const lat = latitude * Math.PI / 180;
    const x = R * Math.cos(lat) * Math.sin(lon);
    const y = R * Math.sin(lat);
    const z = R * Math.cos(lon) * Math.cos(lat);
    return { x, y, z };
}
